package com.newtouch.xcd.admin.ma.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.newtouch.xcd.cms.entity.Product;
import com.newtouch.xcd.cms.service.ProductService;
import com.newtouch.xcd.common.constants.BaseDict;
import com.newtouch.xcd.common.constants.RedisKeyDict;
import com.newtouch.xcd.common.constants.ResponseCode;
import com.newtouch.xcd.common.to.CommonResult;
import com.newtouch.xcd.common.utils.DateUtils;
import com.newtouch.xcd.common.utils.NumberUtils;
import com.newtouch.xcd.common.utils.StrUtils;
import com.newtouch.xcd.config.entity.ProductMark;
import com.newtouch.xcd.ma.vo.*;
import com.newtouch.xcd.cms.service.ProductMarkService;
import com.newtouch.xcd.pms.entity.XcdFundOrder;
import com.newtouch.xcd.pms.service.XcdFundOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@CrossOrigin
@RestController
@Api(tags = "MaController", description = "2.4我的预约ma(myAppointment)")
@RequestMapping("/ma")
public class MaController {

    @Reference
    private ProductMarkService productMarkService;

    @Reference
    private ProductService productService;

    @Reference
    private XcdFundOrderService xcdFundOrderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 2.4.01 产品推广与预约
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "2.4.01 产品推广与预约")
    @PostMapping(value = "/queryProductPromotionAndAppointment")
    public CommonResult<MaQueryProductPromotionAndAppointmentRsp> queryProductPromotionAndAppointment(@Valid @RequestBody MaQueryProductPromotionAndAppointmentReq req, BindingResult result, HttpServletRequest request) {

        String productName = req.getProductName();

        List<ProductMark> productMarks = this.productMarkService.allConfig();

        List<ProductMark> hotList = productMarks.stream().filter(o -> BaseDict.ProductMark.HOT.getCode().equals(o.getMark())).collect(Collectors.toList());
        List<ProductMark> hisList = productMarks.stream().filter(o -> BaseDict.ProductMark.HIS.getCode().equals(o.getMark())).collect(Collectors.toList());

        List<FundProducts> hotProducts = new ArrayList<>();
        List<FundProducts> historicalProducts = new ArrayList<>();

        for (ProductMark productMark : hotList) {
            hotProducts.add(pingFundProducts(productMark, BaseDict.FundProductHotOrHisFlag.F00.getCode()));
        }

        for (ProductMark productMark : hisList) {
            historicalProducts.add(pingFundProducts(productMark, BaseDict.FundProductHotOrHisFlag.F01.getCode()));
        }

        if (StrUtils.isNotBlank(productName)) {
            hotProducts = hotProducts.stream().filter(o -> o.getFinancialProductName().contains(productName)).collect(Collectors.toList());
            historicalProducts = historicalProducts.stream().filter(o -> o.getFinancialProductName().contains(productName)).collect(Collectors.toList());
        }

        MaQueryProductPromotionAndAppointmentRsp rsp = new MaQueryProductPromotionAndAppointmentRsp();
        rsp.setHotProducts(hotProducts);
        rsp.setHistoricalProducts(historicalProducts);

        return CommonResult.success(rsp);
    }

    private FundProducts pingFundProducts(ProductMark productMark, String fundProductHotOrHisFlag) {
        FundProducts fundProducts = new FundProducts();
        fundProducts.setProductId(productMark.getProductId());
        fundProducts.setFinancialProductName(StrUtils.calFinProductName(productMark.getName()));

        Product product = this.productService.getById(Convert.toInt(productMark.getProductId()));

        if (product != null) {

            BigDecimal expectedYield = NumberUtils.formatNumber(Convert.toStr(product.getYqsyl()));
            if (BigDecimal.ZERO.compareTo(expectedYield) != 0) {
                fundProducts.setExpectedYield(NumberUtils.money(product.getYqsyl(), "#.#"));
            }

            fundProducts.setFundInvestmentYear(product.getCrmKauocp());
            fundProducts.setMinimumInvestmentAmount(StrUtils.calTenThousandAmount(product.getCrmOmwlzy()));
        }

        fundProducts.setFundProductHotOrHisFlag(fundProductHotOrHisFlag);
        return fundProducts;
    }

    /**
     * 2.4.02查询产品详情
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "2.4.02查询产品详情")
    @PostMapping(value = "/queryProductDetail")
    public CommonResult<MaQueryProductDetailRsp> queryProductDetail(@Valid @RequestBody MaQueryProductDetailReq req, BindingResult result, HttpServletRequest request) {
        String productId = req.getProductId();

        ProductMark productMark = this.productMarkService.queryByProductId(productId);
        if (productMark == null) {
            return CommonResult.error(ResponseCode.R407.getCode(), "输入的产品ID不存在。");
        }

        Product product = this.productService.getById(Convert.toInt(productId));

        MaQueryProductDetailRsp rsp = new MaQueryProductDetailRsp();
        rsp.setProductId(productId);

        rsp.setProductName(StrUtils.calFinProductName(productMark.getName()));

        rsp.setProductImageUrl(productMark.getUrl());

        if (BaseDict.ProductMark.HOT.getCode().equals(productMark.getMark())) {
            rsp.setFundProductHotOrHisFlag(BaseDict.FundProductHotOrHisFlag.F00.getCode());
        } else {
            rsp.setFundProductHotOrHisFlag(BaseDict.FundProductHotOrHisFlag.F01.getCode());
        }

        if (product != null) {
            rsp.setProductAdministrator(product.getCrmWhusbe());
        }

        return CommonResult.success(rsp);
    }

    /**
     * 2.4.03 预约信息填写
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "2.4.03 预约信息填写")
    @PostMapping(value = "/submitAppointmentInformation")
    public CommonResult<MaAppointmentInformationRsp> submitAppointmentInformation(@Valid @RequestBody MaAppointmentInformationReq req, BindingResult result, HttpServletRequest request) {
        //增加一把分段锁，做线程安全。锁ID：XCD:PMS:SMS_CODE_FUND_PRODUCT:手机号
        //手机号
        String phone = req.getCustomerPhone();
        String bookAmount=req.getBookingAmount();
        String productId = req.getProductId();
        Product product = this.productService.getById(Convert.toInt(productId));
        if (product == null) {
            return CommonResult.error(ResponseCode.R407.getCode(), "产品ID不正确，没有这一款产品。");
        }
        String productName = StrUtils.calFinProductName(product.getName());
        RLock rLock = this.redissonClient.getLock(RedisKeyDict.XcdPms.XCD_PMS_FUND_PRODUCT_SEGMENT.getCode() + phone);
        Boolean flag = null;
        try {
            flag = rLock.tryLock(30, TimeUnit.SECONDS);

            if (flag) {
                //获取我的预约
                String reFundProductRedisKey = RedisKeyDict.XcdProductFund.MY_FUND_PRODUCT_APPOINTMENT.getCode() + req.getProductId() + ":" + req.getCustomerName() + "_"
                        + req.getCustomerPhone() + "_" + req.getBookingAmount();
                Object reFundProductRedisKeyValue = this.redisTemplate.opsForValue().get(reFundProductRedisKey);

                if (reFundProductRedisKeyValue == null) {
                    XcdFundOrder xcdFundOrder = new XcdFundOrder();
                    xcdFundOrder.setId(IdUtil.fastSimpleUUID());
                    xcdFundOrder.setRequestId(IdUtil.fastSimpleUUID());
                    xcdFundOrder.setProductId(productId);
                    xcdFundOrder.setCustomerName(req.getCustomerName());
                    xcdFundOrder.setCustomerPhone(req.getCustomerPhone());
                    xcdFundOrder.setBookingAmount(bookAmount);
                    xcdFundOrder.setReference(req.getReference());
                    xcdFundOrder.setBookSubmitTime(DateUtils.now());
                    xcdFundOrder.setBookStatus(BaseDict.BookStatus.B00.getCode());
                    xcdFundOrder.setCreateTime(DateUtils.now());
                    xcdFundOrder.setUserCode(BaseDict.UserCode.AUTO.getCode());
                    xcdFundOrder.setDataLevel(BaseDict.DataLevel.D0.getCode());
                    xcdFundOrder.setVersion(1);

                    this.xcdFundOrderService.save(xcdFundOrder);

                    this.redisTemplate.opsForValue().set(reFundProductRedisKey, DateUtils.now(), 1, TimeUnit.DAYS);
                }
            }

        } catch (Exception e) {
            return CommonResult.error(ResponseCode.R407.getCode(), e.getMessage());
        } finally {
            if (rLock.isLocked()) {
                rLock.unlock();
            }
        }

        MaAppointmentInformationRsp rsp = new MaAppointmentInformationRsp();
        rsp.setAppointmentSuccessfulInformation("尊敬的" + req.getCustomerName() + "，您已成功预约" + productName + "基金产品，客户经理将在2个工作日内与您联系，请保持电话通畅，十分感谢您的支持！");
        return CommonResult.success(rsp);
    }
}
